jsx3.lang.Class.defineClass("ux.megatron.util.Dwr",
    null,
    null,
    function(myDwr) {
        /**
         * Default myDwr path
         */
        myDwr._DWRPATH = "/cdbloan/myDwr";
        myDwr._dwrEngineLoaded = false;

        myDwr._queries = [];
        myDwr._inBatch = false;
        myDwr._batchCount = 0;

        myDwr._DOCSPATH = "ux/cdb/admin/docs/";
        myDwr._liveMode = false;

        myDwr.setLiveMode = function(ifLiveMode){
            myDwr._liveMode = ifLiveMode;
        };

        myDwr.setDocsPath = function(path) {
            myDwr._DOCSPATH = path;
        };
        
        /**
         * Set myDwr path and save as a global property of Main object. This function should be called at initialization of app.
         */
        myDwr.setDwrPath = function(path) {
            myDwr._DWRPATH = path;
        };
        
        /**
         * Get myDwr path
         */
        myDwr.getDwrPath = function() {
            return myDwr._DWRPATH;
        };


        myDwr.loadStaticData = function(dwrClass, dwrMethod, myDwrParams) {
            try {
                var absPath, req, content;
                
                if(myDwrParams && myDwrParams[0]) {
                    req = new jsx3.net.Request();
                    absPath = ux.megatron.Main.getServer().resolveURI(myDwr._DOCSPATH + dwrClass + "/" + dwrMethod + "_" + myDwrParams[0] + ".js");
                    req.open("GET", absPath, false);
                    req.send();
                    content = req.getResponseText();
                }

                if(!req || req.getStatus() == 404) {
                    req = new jsx3.net.Request();
                    absPath = ux.megatron.Main.getServer().resolveURI(myDwr._DOCSPATH + dwrClass + "/" + dwrMethod + ".js");
                    req.open("GET", absPath, false);
                    req.send();
                    content = req.getResponseText();
                }

                if (req.getStatus() != 200) {
                    throw "Status is " + req.getStatus();
                }
                else if (!content) {
                    throw "ResponseText is null";
                }
                else if (content.indexOf("Matrix_cdbadmin_Login_Test_For_SessionTimeOut") != -1) {
                    //TODO:: by Eric
                    throw "Matrix_cdbadmin_Login_Test_For_SessionTimeOut is loaded. Not a valid Java Script";
                }
                var dwrObject = ux.megatron.util.JSON.StringtoJSON(content);
                return(dwrObject);
            } catch(ex) {
                alert("Error in load static data (" + dwrClass +"."+ dwrMethod +") in ux.megatron.util.dwr ::" + ex);
                myDwr.log("Error in load static data (" + dwrClass +"."+ dwrMethod +"), :::" + ex, jsx3.util.Logger.ERROR);
                return null;
            }
        };

        /**
         * Loads DWR related packages like engine, util and Service
         **/
        myDwr.loadDwrEngine = function(path) {
            if(ux.megatron.Main.isFileSystem()) { return; }
            var path = path ? path : myDwr._DWRPATH ;
            var server = ux.megatron.Main.getServer();
            if (!myDwr._dwrEngineLoaded) {
                try {
                    myDwr.log("loading Dwr engine.");
                    //server.loadInclude( path + "/engine.js", null, "script", true);
                    //server.loadInclude( path + "/util.js", null, "script", true);
                    var _setErrorHandler = function(){
                        if(window["DWREngine"]){
                            DWREngine.setErrorHandler(function(message, ex){
                                //console.log(message, ex);
                                var title = server.getDynamicProperty("@cdb@sessionTimeoutTitle");
                                var content = server.getDynamicProperty("@cdb@sessionTimeoutContent");
                                var ok = server.getDynamicProperty("@cdb@Mechanism@CooOrg@ButtonOK");
								ux.megatron.Dialog.alert(title, content, function(objDialog){
									myDwr.callDwr("LoginUCC", "logOut", [], myDwr, function(dwrObject){});
									setTimeout(function(){
										window.onbeforeunload = function(e){};
										document.location.replace('/');
									}, 100);
                                }, ok);
                            });
                        } else {
                            setTimeout(_setErrorHandler, 100);
                        }
                    };
                    /*
                    _setErrorHandler = function(){
                        if(window["DWREngine"]){
                            DWREngine.setErrorHandler(function(message, ex){
                                ux.megatron.Dialog.alert("Server Exception", ex.javaClassName, function(objDialog){
                                    objDialog.doClose();
                                }, "OK");
                            });
                        } else {
                            setTimeout(_setErrorHandler, 100);
                        }
                    };
                    */
                    _setErrorHandler();
                    myDwr._dwrEngineLoaded = true;
                }
                catch(e) {
                    myDwr.log("Error loading DWR resources");
                    throw new jsx3.lang.Exception("Error loading DWR resources", e);
                }
            }
        };

        /**
         * Load Dwr Interface javascript file asynchronous
         **/
        myDwr.loadDwrClass = function(myDwrInterface, myDwrClass, _loadDwrClassCallback){
            //console.log("loadDwrClass");
            if(ux.megatron.Main.isFileSystem()) { return; }
            var _loadDwrClass = function() {
                if(window[myDwrClass]) {
                    myDwr.loading = false;
                    myDwr._endLoadInterface({dwrInterface: myDwrInterface, dwrClass: myDwrClass });
                    _loadDwrClassCallback();
                } else {
                    try {
                        if(!myDwr.loading) {
                            myDwr._beginLoadInterface({dwrInterface: myDwrInterface, dwrClass: myDwrClass});
                            ux.megatron.Main.getServer().loadInclude(myDwr._DWRPATH + "/interface/" + 
                                myDwrInterface + ".js", null, "script", true);
                            myDwr.loading = true;
                        }
                        setTimeout(_loadDwrClass, 100);
                    } catch(ex) {
                        alert(ex.message);
                        myDwr.log("Error loading Dwr Interface " + myDwrInterface);
                    }
                }
            };
            _loadDwrClass();
        };
        myDwr.registerCallbackHandler = function(handler, scope){
            if(!myDwr.callbackHandlers){
                myDwr.callbackHandlers = [];
            }
            if(!scope){
                myDwr.callbackHandlers.push(handler);
            } else {
                myDwr.callbackHandlers.push(jsx3.makeCallback(handler, scope));
            }
        };
        myDwr.runCallbackHandler = function(dwrObject) {
            if(myDwr.callbackHandlers) {
                for(var i = 0; i < myDwr.callbackHandlers.length; i ++) {
                    myDwr.callbackHandlers[i](dwrObject);
                };
            }
        };
        myDwr.registerStatusHandler = function(handler, scope) {
            if(!myDwr.statusHandlers) {
                myDwr.statusHandlers = [];
            }
            if(!scope) {
                myDwr.statusHandlers.push(handler); 
            } else {
                myDwr.statusHandlers.push(jsx3.makeCallback(handler, scope));
            }
        };

        myDwr.runStatusHandler = function(message) {
            if(myDwr.statusHandlers) {
                for(var i=0; i<myDwr.statusHandlers.length; i++) {
                    handler = myDwr.statusHandlers[i];
                    handler(message);
                }
            }
        };

        /**
         * defalut Status handler, just log some information.
         */
        myDwr.logStatusHandler = function(message){
            var klass, method, status, remaining, dwrInterface;
            var queryType = message.objQuery.dwrType;
            if(queryType == "BeginQuery" || queryType == "EndQuery") {
                klass = message.objQuery.dwrClass;
                method = message.objQuery.dwrMethod;
                status = message.objQuery.dwrStatus;
                remaining = message.dwrRemaining;

                myDwr.log(queryType + "-> " + klass + "." + method + " " + status + ", " + remaining + " query(s) remaining");
            } else {
                dwrInterface = message.objQuery.dwrInterface;
                klass = message.objQuery.dwrClass;
                status = message.objQuery.dwrStatus;

                myDwr.log(queryType + "-> " + dwrInterface + "." + klass + " " + status);
            }
        };

        myDwr.registerStatusHandler(myDwr.logStatusHandler);

        myDwr.addToBatch = function(){
            myDwr._batchCount ++;
            //console.log(myDwr._batchCount);
        };

        myDwr.subFromBatch = function(){
            myDwr._batchCount --;
            //console.log(myDwr._batchCount);
        };

        myDwr.beginBatch = function(){
            //console.log("beginBatch");
            myDwr._inBatch = true;
            if(window.dwr) { dwr.engine.beginBatch(); }

        };

        myDwr.endBatch = function(timeout){
            //console.log("endBatch");
            if(myDwr._batchCount){
                setTimeout(myDwr.endBatch, 100);
            }
            else {
                if(window.dwr) { dwr.engine.endBatch(timeout); }
                myDwr._inBatch = false;
            }
        };
        
        /**
         * Call function of myDwr object with checking missing Object and load them before.
         */
        myDwr.callDwr = function(myDwrClass, myDwrMethod, myDwrParams, callbackContext, callback, myDwrInterface) {
            if(!myDwr._liveMode){
                callback.call(callbackContext, myDwr.loadStaticData(myDwrClass, myDwrMethod, myDwrParams));
                return;
            } else {
                //console.log("callDwr");
                try{
                    if(myDwr._inBatch) {
                        myDwr.addToBatch();
                    }
                    if(ux.megatron.Main.isFileSystem()) { return; }
                    if(!myDwr._dwrEngineLoaded){
                        myDwr.loadDwrEngine();
                        if(!myDwr._dwrEngineLoaded){
                            alert("Can not load myDwr engine!");
                            return;
                        }
                    }
                    if(!window[myDwrClass]) {
                        if(!myDwrInterface) {
                            myDwrInterface = myDwrClass;
                        }
                        myDwr.loadDwrClass(myDwrInterface, myDwrClass, function(){
                            //console.log("_loadDwrClassCallback");
                            myDwr._doQuery(myDwrClass, myDwrMethod, myDwrParams, callbackContext, callback);
                        });
                    } else {
                        myDwr._doQuery(myDwrClass, myDwrMethod, myDwrParams, callbackContext, callback);
                    }
                } catch(ex){
                    alert(ex);
                }
            }
        };

        /**
         * @private
         */
        myDwr._doQuery = function(myDwrClass, myDwrMethod, myDwrParams, callbackContext, callback){
            //console.log("_doQuery");
            var objQuery = {dwrClass: myDwrClass, dwrMethod: myDwrMethod};
			var dwrPerformance = ux.megatron.util.Performance.beginBenchmark("Loading class from BS : " + myDwrClass + "->" + myDwrMethod);
            myDwr._beginQuery(objQuery);
            myDwr._realCallDwr(myDwrClass, myDwrMethod, myDwrParams, function(myDwrObject){
                try{
                    // for generating static data
                    //console.log("DWR Class: " + myDwrClass);
                    //console.log("DWR Method: " + myDwrMethod);
                    //console.log("DWR Response: " + JSON.stringify(myDwrObject));
                    myDwr.runCallbackHandler(myDwrObject);
                    myDwr._endQuery(objQuery);
					ux.megatron.util.Performance.endBenchmark(dwrPerformance);
                    callback.call(callbackContext, myDwrObject);
                } catch(ex) {
                    //console.log(ex);
                }
            }, objQuery);
        };
        
        /**
         * @private
         */
        myDwr._realCallDwr = function(myDwrClass, myDwrMethod, myDwrParams, _callback, objQuery){
            //console.log("_callDwr");
            try{
                myDwrParams = myDwrParams || [];
                myDwrParams.push(_callback);
                if(myDwr._inBatch) {
                    myDwr.subFromBatch();
                }
                window[myDwrClass][myDwrMethod].apply(this, myDwrParams);
            } catch(ex) {
                console.log(ex);
                myDwr._endQuery(objQuery);
            }
        };

        /**
         * @private
         */
        myDwr._beginQuery = function(objQuery){
            myDwr._queries.push(objQuery);
            objQuery.dwrStatus = "started";
            objQuery.dwrType = "BeginQuery";
            var message = {objQuery: objQuery, dwrRemaining: myDwr._queries.length};
            myDwr.runStatusHandler(message);
        };

        /**
         * @private
         */
        myDwr._endQuery = function(objQuery){
            for(var i = 0; i < myDwr._queries.length; i ++){
                if((myDwr._queries[i].myDwrClass== objQuery.myDwrClass) && (myDwr._queries[i].myDwrMethod == objQuery.myDwrMethod)){
                    myDwr._queries.splice(i, 1);
                    break;
                }
            }
            objQuery.dwrStatus = "finished";
            objQuery.dwrType = "EndQuery";
            var message = {objQuery: objQuery, dwrRemaining: myDwr._queries.length};
            myDwr.runStatusHandler(message);
        };

        myDwr._beginLoadInterface = function(objQuery) {
            objQuery.dwrStatus = "started";
            objQuery.dwrType = "BeginLoadInteface";
            var message = {objQuery: objQuery};
            myDwr.runStatusHandler(message);
        };

        myDwr._endLoadInterface = function(objQuery) {
            objQuery.dwrStatus = "finished";
            objQuery.dwrType = "EndLoadInteface";
            var message = {objQuery: objQuery};
            myDwr.runStatusHandler(message);
        };

    /**********************************************************************
     *****************Content of gi.js from myDwr package********************
     */
    /*
     * Copyright 2005 Joe Walker
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *     http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */

        /**
         * Convert a javascript object into a CDF document with the given jsxid
         * @param {Object} data The data that we want to publish in a CDF document
         * @param {String} jsxid The jsxid of the returned document
         */
        myDwr.toCdfDocument = function(data, jsxid, mapping, copying) {
          jsxid = jsxid || "jsxroot";
          if(mapping) {
              myDwr.mapping = mapping;
          } else {
              myDwr.mapping = {};
          }
          if(copying) {
              myDwr.copying = copying;
          } else {
              myDwr.copying = {};
          }
          var cdfstr = myDwr._toCdfDocumentString(data, jsxid);
          var cdf = jsx3.xml.CDF.Document.newDocument();
          cdf.loadXML(cdfstr);
          return cdf;
        };
        /**
         *Convert a javascript object into a CDF document with the given jsxid, that's just for tree
         *@param {String}attr  The attribute that will show in the jsxtext
         */
        myDwr.toCdfDocument_forTree = function(data, jsxid, mapping,attr) {
          jsxid = jsxid || "jsxroot";
          if(mapping) {
              dwr.mapping = mapping;
          } else {
              dwr.mapping = {};
          }
          var cdfstr;
          if (data instanceof Object) {
                 var reply = "", element;
                 for (element in data) {  
                    if(data[element] instanceof Object){//content
                       for(ele in data[element] ){  
                           if(data[element][ele] instanceof Array){   //data
                              for(var i=0; i<data[element][ele].length;i++){
                                 myDwr._traversal(data[element][ele][i],attr);
                              }
                               cdfstr =  myDwr._toCdfDocumentString(data[element][ele], jsxid);
                           }
                       }
                    }
                }
          }
          //console.info(cdfstr);
          var cdf = new jsx3.xml.Document();
          cdf.loadXML(cdfstr);
          return cdf;
        };

        /**
         *Traversal the obj 
         *
         */
        myDwr._traversal=function(obj,attr){
           for(objattr in obj){
             if(typeof obj[objattr] == "string" || obj[objattr] instanceof String){
                   if(objattr==attr){
                         obj.jsxtext = obj[objattr];
                         obj.jsxid   = obj.id;
                   }
               }
               else if(obj[objattr] instanceof Array){
                   for(var i=0;i<obj[objattr].length;i++){
                      if(typeof obj[objattr][i]=="object"){
                         myDwr._traversal(obj[objattr][i],attr);
                      }
                   }
               }
           }
        };

        /**
         *Convert [{{object,property...},property...},{}] to shallow cdf document
         *@param myDwrObjectArray {Array} A array of objects which maybe contain other objects
         */
        myDwr.toShallowCdf = function(myDwrObjectArray){
            var cdfDoc = jsx3.xml.CDF.Document.newDocument();
            var record;
            for(var i=0; i<myDwrObjectArray.length; i++){
                record = {};
                record = myDwr._addPropertiesToRecord(myDwrObjectArray[i], record);
                record.jsxid = i;
                cdfDoc.insertRecord(record, "jsxroot");
            }
            return cdfDoc;
        };

        /**
         *Convert the object's propeties to shallow record's attribute
         *@param obj{object}
         *@param record {jsx3.xml.Entity} 
         */
        myDwr._addPropertiesToRecord = function(obj,record){
            for(var property in obj){
                if(obj[property] === null) {
                    record[property] = "";
                } else if(typeof obj[property] == 'object'){
                    record = myDwr._addPropertiesToRecord(obj[property],record);
                }else{
                    record[property] = obj[property];
                }
            }
            return record;
        };

        /**
         * Convert an XML String into a JSX3 Document.
         * This method just calls jsx3.xml.Document.loadXML(), however since this method
         * is static it can be called as a one-off without setup, which is useful when
         * using pseudo-json.
         * @private
         * @param {String} xmlString The string serialization of the XML
         * @return {jsx3.xml.Document} A JSX3 in-memory model of the XML
         */
        myDwr._loadXml = function(xmlString) {
          var doc = new jsx3.xml.Document();
          doc.loadXML(xmlString);
          return doc;
        };

        /**
         * Convert a javascript object into a CDF RecordSet
         * @param data The data that we want to publish in a CDF record set
         */
        myDwr.toRecordSet = function(data) {
          if (data === null) { return ""; }
          if (data instanceof Array) {
            return myDwr._convertArray(data, "", 0);
          }
          if (data instanceof Object) {
            return myDwr._convertObject(data, "", 0);
          }
          return myDwr._convertOther(data, "root", 0);
        };

        /** @private Convert any Javascript object to a CDF Document string */
        myDwr._toCdfDocumentString = function(data, jsxid) {
          return "<data jsxid='" + jsxid + "'>\n" + myDwr.toRecordSet(data) + "</data>\n";
        };

        /** @private Convert an array to a JSX string */
        myDwr._convertArray = function(data, name, depth) {
          var i, reply = "";
          for (i = 0; i < data.length; i++) {
            reply += myDwr._convertAttributes(data[i], name + i, depth);
          }
          for (i = 0; i < data.length; i++) {
            reply += myDwr._convertElements(data[i], name + i, depth);
          }
          return reply;
        };

        /** @private Convert an object to a JSX string */
        myDwr._convertObject = function(data, name, depth) {
          var reply = "", element;
          for (element in data) {
            reply += myDwr._convertAttributes(data[element], element, depth);
          }
          for (element in data) {
            reply += myDwr._convertElements(data[element], element, depth);
          }
          return reply;
        };

        /** @private Convert an object of unknown type to a JSX string */
        myDwr._convertAttributes = function(data, name, depth) {
          if(myDwr.copying[name]){
              var copyName = myDwr.copying[name];
          } else {
              var copyName = null;
          }
          if(myDwr.mapping[name]){
              name = myDwr.mapping[name];
          }
          if (typeof data == "function") {
            return ""; // ignore functions
          }
          if (typeof data == "string" || data instanceof String) {
            // TODO: escape the string
            if(copyName){
                return " " + name + "='" + data + "' " + copyName + "='" + data + "'";
            } else {
                return " " + name + "='" + data + "'";
            }
          }
          if (typeof data == "object") {
            if (data instanceof Date) {
              if(copyName){
                  return " " + name + "='" + data.toUTCString() + "' " + copyName + "='" + data.toUTCString() + "'";
              } else {
                  return " " + name + "='" + data.toUTCString() + "'";
              }
            }
            return "";
          }
          if(copyName){
              return " " + name + "='" + data + "' " + copyName + "='" + data + "'";
          } else {
              return " " + name + "='" + data + "'";
          }
        };

        /** @private Convert an object of unknown type to a JSX string */
        myDwr._convertElements = function(data, name, depth) {
          var reply, element;
          if (data === null) {
            return ""; // don't create an empty element for null objects
          }
          if (typeof data == "function") {
            return ""; // ignore functions
          }
          if (typeof data == "object") {
            if (data instanceof Date) {
              return "";
            }
            if (data instanceof Array) {
              reply = "";
              if(name != "children"){ reply = myDwr._indent(depth) + "<record index='0' jsxid='" + name + "' jsxtext='" + name + "' >\n"; }
              reply += myDwr._convertArray(data, name + ".", depth + 1);
              if(name != "children"){ reply += myDwr._indent(depth) + "</record>\n"; }
              return reply;
            }
            reply = myDwr._indent(depth) + "<record";
            for (element in data) {
              reply += myDwr._convertAttributes(data[element], element, depth + 1);
            }
            reply += ">\n";
            for (element in data) {
              reply += myDwr._convertElements(data[element], element, depth + 1);
            }
            reply += myDwr._indent(depth) + "</record>\n";
            return reply;
          }
          return "";
        };

        /** @private Do we try to keep the generated source looking good? */
        myDwr._prettyPrint = false;

        /** @private Pretty printing */
        myDwr._indent = function(depth) {
          if (!myDwr._prettyPrint) { return ""; }
          for (var i = 0; i < depth; i++) {
              reply += "  ";
          }
          return reply;
        };

        myDwr.log = function(msg, level) {
            if(!myDwr.LOGGER) {
                myDwr.LOGGER = jsx3.util.Logger.getLogger(myDwr.jsxclass.getName());
                myDwr.log = function(msg, level) {
                    level = level || jsx3.util.Logger.INFO;
                    myDwr.LOGGER.log(level, msg);
                };
                myDwr.log(msg, level);
            }
        };

        myDwr.log("ux.megatron.util.Dwr loaded.");
    }
);